package org.nmgyjt.springboot.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.message.BasicNameValuePair;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author undefine
 */
@Slf4j
public class HttpsService {

    private static int TIME_OUT = 10000;

    private static HttpClient httpclient = null;
    private static final String LOG_INFO = "{}请求返回状态码:{}";
    private static final String UTF_8 = "ust-8";
    private static final int CONNECT_SUC = 200;

    private static MultiThreadedHttpConnectionManager manager = null;

    static {
        manager = new MultiThreadedHttpConnectionManager();
        manager.getParams().setConnectionTimeout(TIME_OUT);
        manager.getParams().setMaxTotalConnections(2000);
        manager.getParams().setDefaultMaxConnectionsPerHost(400);
        manager.getParams().setSoTimeout(TIME_OUT);
        httpclient = new HttpClient(manager);
    }

    public static String get(String url) {
        return get(url, null, TIME_OUT);
    }

    public static <T> T get(String url, Class<T> clazz) {
        return get(url, null, TIME_OUT, clazz);
    }

    /**
     * 最好不要使用String返回，会拷贝多一份数据，可以使用byte[]或stream返回
     *
     * @param url
     * @param timeOut 毫秒
     * @return String
     */
    public static <T> T get(String url, int timeOut, Class<T> clazz) {
        return get(url, null, timeOut, clazz);
    }

    public static String get(String url, int timeOut) {
        return get(url, null, timeOut);
    }


    public static String get(String url, List<BasicNameValuePair> headers, int timeout) {
        byte[] resp = getResultAsByteArray(url, headers, timeout);
        if (resp == null) {
            return null;
        }

        return new String(resp);
    }

    public static <T> T get(String url, List<BasicNameValuePair> headers, int timeout, Class<T> clazz) {
        InputStream resp = getResultAsStream(url, headers, timeout);
        if (resp == null) {
            return null;
        }
        try {
            return SerializeUtil.get().readValue(resp, clazz);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static InputStream getResultAsStream(String url, List<BasicNameValuePair> headers, int timeout) {
        InputStream responseBody = null;
        GetMethod httpget = new GetMethod(url);
        if (timeout > 0) {
            HttpMethodParams params = new HttpMethodParams();
            params.setSoTimeout(timeout * 1000);
            httpget.setParams(params);
        }
        try {
            try {
                if (headers != null) {
                    for (BasicNameValuePair bnvp : headers) {
                        httpget.setRequestHeader(bnvp.getName(), bnvp.getValue());
                    }
                    int resp = httpclient.executeMethod(httpget);
                    if (resp == CONNECT_SUC) {
                        responseBody = httpget.getResponseBodyAsStream();
                    } else {
                        log.info(LOG_INFO, url, resp);
                    }
                }
            } finally {
                httpget.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return responseBody;
    }

    public static byte[] getResultAsByteArray(String url, List<BasicNameValuePair> headers, int timeout) {
        byte[] responseBody = null;
        GetMethod httpget = new GetMethod(url);
        if (timeout > 0) {
            HttpMethodParams params = new HttpMethodParams();
            params.setSoTimeout(timeout * 1000);
            httpget.setParams(params);
        }
        try {
            try {
                if (headers != null) {
                    for (BasicNameValuePair bnvp : headers) {
                        httpget.setRequestHeader(bnvp.getName(), bnvp.getValue());
                    }
                    int resp = httpclient.executeMethod(httpget);
                    if (resp == CONNECT_SUC) {
                        responseBody = httpget.getResponseBody();
                    } else {
                        log.info(LOG_INFO, url, resp);
                    }

                }

            } finally {
                httpget.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return responseBody;
    }

    public static void get(String url, int timeout, List<BasicNameValuePair> headers, HttpResponseHandler handler) {

        GetMethod httpget = new GetMethod(url);
        if (timeout > 0) {
            HttpMethodParams params = new HttpMethodParams();
            params.setSoTimeout(timeout * 1000);
            httpget.setParams(params);
        }
        try {
            try {
                if (headers != null) {
                    for (BasicNameValuePair bnvp : headers) {
                        httpget.setRequestHeader(bnvp.getName(), bnvp.getValue());
                        httpclient.executeMethod(httpget);
                        if (handler != null) {
                            handler.handle(httpget);
                        }
                    }
                }
            } finally {
                httpget.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 最好使用postReturnStream,其次再考虑postReturnByteArray
     *
     * @param url
     * @param params
     * @param headers
     * @return
     */
    public static String post(String url, List<BasicNameValuePair> params, List<BasicNameValuePair> headers) {
        byte[] resp = postReturnByteArray(url, params, headers);
        if (resp == null) {
            return null;
        }
        return new String(resp);
    }

    public static <T> T post(String url, List<BasicNameValuePair> params,
                             List<BasicNameValuePair> headers, Class<T> clazz) {
        InputStream resp = postReturnStream(url, params, headers);
        if (resp == null) {
            return null;
        }
        try {
            return SerializeUtil.get().readValue(resp, clazz);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static InputStream postReturnStream(String url, List<BasicNameValuePair> params,
                                               List<BasicNameValuePair> headers) {
        InputStream body = null;
        PostMethod post = new PostMethod(url);
        post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf-8");
        try {
            if (headers != null) {
                for (BasicNameValuePair nvp : headers) {
                    post.addRequestHeader(nvp.getName(), nvp.getValue());
                }
            }
            if (params != null) {
                for (BasicNameValuePair nvp : params) {
                    post.addParameter(nvp.getName(), nvp.getValue());
                }
            }
            try {
                int result = httpclient.executeMethod(post);
                if (result == CONNECT_SUC) {
                    body = post.getResponseBodyAsStream();
                } else {
                    log.debug(LOG_INFO, url, result);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        } finally {
            post.releaseConnection();
        }
        return body;
    }

    /**
     * 请优先考虑postReturnStream
     *
     * @param url
     * @param params
     * @param headers
     * @return
     */
    public static byte[] postReturnByteArray(String url, List<BasicNameValuePair> params,
                                             List<BasicNameValuePair> headers) {
        byte[] body = null;
        PostMethod post = new PostMethod(url);
        try {
            if (headers != null) {
                for (BasicNameValuePair nvp : headers) {
                    post.addRequestHeader(nvp.getName(), nvp.getValue());
                }
            }

            if (params != null) {
                Map paramsMap = new HashMap();
                if (headers.contains("application/json")) {
                    for (BasicNameValuePair nvp : params) {
                        paramsMap.put(nvp.getName(), nvp.getValue());
                    }
                    post.setRequestBody(JSONObject.toJSONString(paramsMap));
                } else {
                    for (BasicNameValuePair nvp : params) {
                        post.addParameter(nvp.getName(), nvp.getValue());
                    }
                }
            }
            try {
                int result = httpclient.executeMethod(post);
                if (result == CONNECT_SUC) {
                    body = post.getResponseBody();
                } else {
                    log.debug(LOG_INFO, url, result);
                }
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        } finally {
            post.releaseConnection();
        }
        return body;
    }

    /**
     * @param url
     * @param jsonParams 暂时没用
     * @param headers
     * @param handler
     */
    public static void httpDelete(String url, String jsonParams, List<BasicNameValuePair> headers,
                                  HttpResponseHandler handler) {
        /**
         * 将JSON进行UTF-8编码,以便传输中文
         */
        try {
            DeleteMethod httpPost = new DeleteMethod(url);
            if (headers != null) {
                for (BasicNameValuePair nvp : headers) {
                    httpPost.addRequestHeader(nvp.getName(), nvp.getValue());
                }
            }

            try {
                httpclient.executeMethod(httpPost);
                if (handler != null) {
                    handler.handle(httpPost);
                }

            } finally {
                httpPost.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    /**
     * 返回的是请求结果码
     */
    public static void httpPostWithJSON(String url, String jsonParams, List<BasicNameValuePair> headers,
                                        HttpResponseHandler handler) {
        /**
         * 将JSON进行UTF-8编码,以便传输中文
         */
        try {
            PostMethod httpPost = new PostMethod(url);
            if (headers != null) {
                for (BasicNameValuePair nvp : headers) {
                    httpPost.addRequestHeader(nvp.getName(), nvp.getValue());
                }
            }
            StringRequestEntity se = new StringRequestEntity(jsonParams, "application/json", "utf-8");
            httpPost.setRequestEntity(se);
            try {
                httpclient.executeMethod(httpPost);
                handler.handle(httpPost);
            } finally {
                httpPost.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    public static <T> T httpPostWithJSON(String url, String jsonParams, List<BasicNameValuePair> headers, Class<T> clazz) {
        byte[] resp = httpPostWithJSON(url, jsonParams, headers);
        try {
            return SerializeUtil.get().readValue(resp, clazz);
        } catch (Exception e) {
            log.error(e.getMessage());
            return null;
        }
    }

    public static byte[] httpPostWithJSON(String url, String jsonParams, List<BasicNameValuePair> headers) {
        /**
         * 将JSON进行UTF-8编码,以便传输中文
         */
        try {
            PostMethod httpPost = new PostMethod(url);
            if (headers != null) {
                for (BasicNameValuePair nvp : headers) {
                    httpPost.addRequestHeader(nvp.getName(), nvp.getValue());
                }
            }
            StringRequestEntity se = new StringRequestEntity(jsonParams, "application/json", "utf-8");
            httpPost.setRequestEntity(se);
            try {
                int code = httpclient.executeMethod(httpPost);
                if (code == CONNECT_SUC) {
                    return httpPost.getResponseBody();
                } else {
                    log.info(LOG_INFO, url, code);
                }
            } finally {
                httpPost.releaseConnection();
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }
}
